home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / smooth.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  322 lines

  1. /*
  2.  * $Id: smooth.c,v 0.91 1994/02/20 00:53:12 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *  Purpose:
  26.  *     Smooth an image or a rectangular region of it using a special
  27.  *     convolution kernel, either 3x3, 5x5 or 7x7.
  28.  *
  29.  */
  30.  
  31. #if !defined(lint) && defined(F_ID)
  32. char *id_smo = "$Id: smooth.c,v 0.91 1994/02/20 00:53:12 zhao Pre-Release $";
  33. #endif
  34.  
  35. #include "bit.h"
  36. #include "extern.h"
  37.  
  38. /************** Local variables ********************/
  39.  
  40. static Rect_t smoothreg, *sr;    /* smoothing region     */
  41. static int rbcolor = 1;        /* rubber band color    */
  42. static IPTR saved;        /* input image          */
  43. static int morder;        /* current smooth order */
  44. static int **smooth_mat;    /* smoothing matrix     */
  45. static int changed;        /* raster status        */
  46. static int threshold[3];    /* threshold            */
  47.  
  48.  
  49. /**************** Local functions *************************/
  50.  
  51. static int smooth_init(IPTR, int);
  52. static void set_smooth_mat(FL_OBJECT *, long);
  53. static void create_form_smooth(void);
  54. static FL_FORM *smooth;
  55. static FL_OBJECT *tc[3];    /* threshold counter */
  56.  
  57. /****************************************************************
  58.  * Global entry point
  59.  ****************************************************************/
  60. int
  61. img_smooth(IPTR im)
  62. {
  63.     short val;
  64.     long dev;
  65.  
  66.     create_form_smooth();
  67.     sr = &smoothreg;
  68.     smooth_init(im, 0);
  69.     install_wm_handler(smooth_init);
  70.     bit_show_form(smooth, FL_PLACE_HOTSPOT, 0, "Smooth");
  71.  
  72.     do
  73.       {
  74.       dev = rubber_info(win_id, &val,
  75.                 &sr->x, &sr->y, &sr->w, &sr->h, rbcolor, 15);
  76.       dev = bit_handle_event(dev, val);
  77.       }
  78.     while (dev != KEYBD || val != 27);
  79.  
  80.     set_current_window(win_id);
  81.     rubber_finish();
  82.     bit_hide_form(smooth);
  83.     remove_wm_handler(smooth_init);
  84.     return 0;
  85. }
  86.  
  87. /**********************************************************************
  88.  * Initialize rubber band location. Also handles window repositioning
  89.  * and window resizing
  90.  **********************************************************************/
  91. static int
  92. smooth_init(IPTR im, int wme)
  93. {
  94.     static int oxi, oyi;
  95.  
  96.     set_rubber_obj(RB_RECT);
  97.     set_rubber_bounds(1, im->xi, im->yi, im->w, im->h);
  98.  
  99.     if (wme)
  100.       {
  101.       sr->x += im->xi - oxi;
  102.       sr->y += im->yi - oyi;
  103.       oxi = im->xi;
  104.       oyi = im->yi;
  105.       }
  106.     else
  107.       {
  108.       set_smooth_mat(0, 0);
  109.       sr->x = oxi = im->xi;
  110.       sr->y = oyi = im->yi;
  111.       sr->w = im->w;
  112.       sr->h = im->h;
  113.       }
  114.     return 0;
  115. }
  116.  
  117. /** Select and make smoothing matrix **/
  118.  
  119. /* default smoothing matrix, a 3x3 and a 5x5 */
  120. static short m_sm3x3[3][3] =
  121. {
  122.     {5, 7, 5},
  123.     {7, 8, 7},
  124.     {5, 7, 5}
  125. };
  126.  
  127. static short m_sm5x5[5][5] =
  128. {
  129.     {5, 6, 7, 6, 5},
  130.     {6, 7, 8, 7, 6},
  131.     {7, 8, 8, 8, 7},
  132.     {6, 7, 8, 7, 6},
  133.     {5, 6, 7, 6, 5}
  134. };
  135.  
  136. /* A lot of stronger than both 3x3 and 5x5 */
  137. static short m_sm7x7[7][7] =
  138. {
  139.     {6, 6, 6, 6, 6, 6, 6},
  140.     {6, 7, 7, 7, 7, 7, 6},
  141.     {6, 7, 8, 8, 8, 7, 6},
  142.     {6, 7, 8, 8, 8, 7, 6},
  143.     {6, 7, 8, 8, 8, 7, 6},
  144.     {6, 7, 7, 7, 7, 7, 6},
  145.     {6, 6, 6, 6, 6, 6, 6}
  146. };
  147.  
  148. static void
  149. set_smooth_mat(FL_OBJECT * ob, long q)
  150. {
  151.     static int lastn = -1;
  152.     short *vec;
  153.     int i, j;
  154.  
  155.     q = (ob == 0 ? 1 : fl_get_choice(ob));
  156.     morder = (q == 1 ? 3 : (q == 2 ? 5 : 7));
  157.  
  158.     if (lastn != morder)
  159.       {
  160.       free_mat(smooth_mat);
  161.       smooth_mat = get_mat(morder, morder, sizeof(**smooth_mat));
  162.       for (i = 0; i < morder; i++)
  163.         {
  164.         vec = (morder == 3 ? m_sm3x3[i] :
  165.                (morder == 5 ? m_sm5x5[i] : m_sm7x7[i]));
  166.         for (j = 0; j < morder; j++)
  167.             smooth_mat[i][j] = *(vec + j);
  168.         }
  169.       lastn = morder;
  170.       }
  171. }
  172.  
  173. /************************ undo *******************************/
  174. /* ARGSUSED */
  175. static void
  176. undo_cb(FL_OBJECT * ob, long q)
  177. {
  178.     if (changed)
  179.       {
  180.       free_image(imgptr);
  181.       imgptr = img_dup(saved);
  182.       imgptr->io->display(imgptr, -1, 0);
  183.       changed = 0;
  184.       }
  185. }
  186.  
  187. /****** Save current change, and mark the undo point **********/
  188. /* ARGSUSED */
  189. static void
  190. save_cb(FL_OBJECT * ob, long q)
  191. {
  192.     if (changed)
  193.       {
  194.       free_image(saved);
  195.       saved = img_dup(imgptr);
  196.       changed = 0;
  197.       }
  198. }
  199.  
  200.  
  201. /***** call back routine to initiating smooth ****/
  202. /* ARGSUSED */
  203. static void
  204. smooth_cb(FL_OBJECT * ob, long q)
  205. {
  206.     if (!saved)
  207.     saved = img_dup(imgptr);
  208.     changed = (img_convolv(imgptr, smooth_mat, morder, morder,
  209.                threshold, sr, "Smoothing ...") >= 0);
  210. }
  211.  
  212. /********************* Finish up ******************************/
  213. /* ARGSUSED*/
  214. static void
  215. finish_smooth(FL_OBJECT * ob, long q)
  216. {
  217.     fl_qenter(KEYBD, 27);
  218. }
  219.  
  220. /*************** Solicit threshold input ***********************/
  221. static void
  222. threshold_cb(FL_OBJECT * ob, long q)
  223. {
  224.     threshold[q] = fl_get_counter_value(ob);
  225.  
  226.     if (IS_GRAY(imgptr))
  227.       {
  228.       fl_freeze_form(smooth);
  229.       threshold[0] = threshold[q];
  230.       if (q != 0)
  231.           fl_set_counter_value(tc[0], threshold[0]);
  232.       threshold[1] = threshold[q];
  233.       if (q != 1)
  234.           fl_set_counter_value(tc[1], threshold[1]);
  235.       threshold[2] = threshold[q];
  236.       if (q != 2)
  237.           fl_set_counter_value(tc[2], threshold[2]);
  238.       fl_unfreeze_form(smooth);
  239.       }
  240. }
  241.  
  242. static void
  243. create_form_smooth(void)
  244. {
  245.     FL_OBJECT *obj;
  246.     static int fmade;
  247.     float dx, dy;
  248.  
  249.     if (fmade)
  250.     return;
  251.  
  252.     smooth = fl_bgn_form(FL_UP_BOX, 280.0, 250.0);
  253.     obj = fl_add_button(FL_HB, 0.0, 0.0, 280.0, 250.0, "");
  254.     fl_set_call_back(obj, help_cb, HELP_SMOOTH);
  255.  
  256.     obj = fl_add_text(FL_NORMAL_TEXT, 30.0, 205.0, 220.0, 30.0, "Smooth");
  257.     fl_set_object_lcol(obj, 4);
  258.     fl_set_object_align(obj, FL_ALIGN_CENTER);
  259.     fl_set_object_lstyle(obj, FL_BOLD_STYLE);
  260.     fl_set_object_lsize(obj, 14.0);
  261.  
  262.     obj = fl_add_choice(FL_NORMAL_CHOICE, 30.0, 140.0, 85.0, 25.0, "Order");
  263.     fl_set_object_boxtype(obj, FL_ROUNDED_BOX);
  264.     fl_set_object_lsize(obj, 10.0);
  265.     fl_set_object_align(obj, FL_ALIGN_TOP);
  266.     fl_set_object_lstyle(obj, FL_BOLD_STYLE);
  267.     fl_set_choice_fontsize(obj, 10.0);
  268.     fl_addto_choice(obj, "3x3");
  269.     fl_addto_choice(obj, "5x5");
  270.     fl_addto_choice(obj, "7x7");
  271.     fl_set_call_back(obj, set_smooth_mat, 0);
  272.  
  273.     obj = fl_add_button(FL_NB, 30.0, 90.0, 85.0, 30.0, "Smooth");
  274.     fl_set_object_lsize(obj, 10.0);
  275.     fl_set_object_color(obj, FL_MAGIC1, FL_YELLOW);
  276.     fl_set_call_back(obj, smooth_cb, 0);
  277.     fl_set_form_hotspot(smooth, 30.0 + 40.0, 90.0 + 15.0);
  278.  
  279.     /* the threshold */
  280.     tc[0] = obj = fl_add_counter(FL_NC, 135.0, 140.0, 125.0, 25.0, "Threshold");
  281.     fl_set_object_color(obj, 47, 1);
  282.     fl_set_object_lsize(obj, 10.0);
  283.     fl_set_object_align(obj, FL_ALIGN_TOP);
  284.     fl_set_counter_bounds(obj, 0.0, (float) PCMAXV);
  285.     fl_set_counter_precision(obj, 0);
  286.     fl_set_counter_step(obj, 1.0, 10.0);
  287.     fl_set_counter_value(obj, (float) threshold[0]);
  288.     fl_set_call_back(obj, threshold_cb, 0);
  289.  
  290.     tc[1] = obj = fl_add_counter(FL_NC, 135.0, 115.0, 125.0, 25.0, "");
  291.     fl_set_object_color(obj, 47, 2);
  292.     fl_set_object_lsize(obj, 10.0);
  293.     fl_set_counter_bounds(obj, 0.0, (float) PCMAXV);
  294.     fl_set_counter_precision(obj, 0);
  295.     fl_set_counter_step(obj, 1.0, 10.0);
  296.     fl_set_counter_value(obj, (float) threshold[1]);
  297.     fl_set_call_back(obj, threshold_cb, 1);
  298.  
  299.     tc[2] = obj = fl_add_counter(FL_NC, 135.0, 90.0, 125.0, 25.0, "");
  300.     fl_set_object_lsize(obj, 10.0);
  301.     fl_set_counter_bounds(obj, 0.0, (float) PCMAXV);
  302.     fl_set_counter_precision(obj, 0);
  303.     fl_set_counter_step(obj, 1.0, 10.0);
  304.     fl_set_counter_value(obj, (float) threshold[2]);
  305.     fl_set_call_back(obj, threshold_cb, 2);
  306.  
  307.     dx = 75.0;
  308.     dy = 27;
  309.     obj = fl_add_button(FL_NB, 25.0, 15.0, dx, dy, "Save");
  310.     fl_set_object_lsize(obj, 10.0);
  311.     fl_set_call_back(obj, save_cb, 0);
  312.     obj = fl_add_button(FL_NB, 100.0, 15.0, dx, dy, "Undo");
  313.     fl_set_object_lsize(obj, 10.0);
  314.     fl_set_call_back(obj, undo_cb, 0);
  315.     obj = fl_add_button(FL_NB, 175.0, 15.0, dx, dy, "Done");
  316.     fl_set_object_lsize(obj, 10.0);
  317.     fl_set_call_back(obj, finish_smooth, 0);
  318.  
  319.     fl_end_form();
  320.     fmade = 1;
  321. }
  322.